# -*- coding: utf-8 -*-
import sys

sys.path.append('/root/anaconda3/lib/python3.6/site-packages')

from multiprocessing import Process
from multiprocessing import Pool
from pymongo import MongoClient
from bs4 import UnicodeDammit
from bs4 import BeautifulSoup
import jieba.posseg as pseg
from urllib import request
from urllib import parse
import numpy as np
import requests
import datetime
import pymongo
import random
import codecs
import json
import pprint
import time
import ssl
import os
import re

headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'en,zh-CN;q=0.9,zh;q=0.8,en-US;q=0.7',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'Host': 'company.51job.com',
    'Pragma': 'no-cache',
    'Referer': 'https://company.51job.com/p1',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
}

headers2 = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'en,zh-CN;q=0.9,zh;q=0.8,en-US;q=0.7',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'Host': 'jobs.51job.com',
    'Pragma': 'no-cache',
    'Referer': 'https://company.51job.com/p3',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
}

headers3 = {
    'Accept': '*/*',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'en,zh-CN;q=0.9,zh;q=0.8,en-US;q=0.7',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Host': 'jobs.51job.com',
    'Origin': 'https://jobs.51job.com',
    'Pragma': 'no-cache',
    'Referer': 'https://jobs.51job.com/all/co2608550.html',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
    'X-Requested-With': 'XMLHttpRequest'
}

headers4 = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'en,zh-CN;q=0.9,zh;q=0.8,en-US;q=0.7',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'Host': 'jobs.51job.com',
    'Pragma': 'no-cache',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
}

headers5 = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'en,zh-CN;q=0.9,zh;q=0.8,en-US;q=0.7',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'Host': 'jobs.51job.com',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36'
}


def token(text):
    return [(tok, pos) for tok, pos in pseg.lcut(text.lower()) if pos not in ['x', 'uj', 'm', 'c'] and len(tok) > 1]


class QIANCHENG_POST():
    def __init__(self, keywords):
        self.cookie = dict()

        random.shuffle(keywords)

        for keyword in keywords:
            totalPage = self.parse_total_page(keyword)

            for page in range(1, int(totalPage) if int(totalPage) <= 30 else 30):
                flag = self.parse_position_list(keyword, page)

                if not flag:
                    break

    def parse_total_page(self, keyword):
        url = 'https://search.51job.com/list/000000,000000,0000,00,9,99,' + keyword + ',2,' + str(1) + '.html?lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare='

        try:
            r = requests.get(url)
        except:
            return self.parse_total_page(keyword)

        page_source = r.text.encode("iso-8859-1").decode('gbk').encode('utf8').decode('utf8')
        soup = BeautifulSoup(page_source, 'html.parser')

        try:
            n = int(re.findall('\d+', soup.find(text = re.compile('页，到第')).parent.text)[0])
        except:
            n = 0

        return n

    def parse_position_list(self, keyword, page):
        url = 'https://search.51job.com/list/000000,000000,0000,00,9,99,' + keyword + ',2,' + str(page) + '.html?lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare='

        try:
            r = requests.get(url)
        except:
            return self.parse_position_list(keyword, page)

        page_source = r.text.encode("iso-8859-1").decode('gbk').encode('utf8').decode('utf8')
        soup = BeautifulSoup(page_source, 'html.parser')

        if len(soup.select('#resultList .el')) < 2:
            return False

        for item in soup.select('#resultList .el')[1:]:
            jobName = item.find(class_ = 't1').find('a').text
            company = item.find(class_ = 't2').get_text()
            location = item.find(class_ = 't3').get_text()
            salary = item.find(class_ = 't4').get_text()
            date = item.find(class_ = 't5').get_text()

            if qushu_qiancheng_position.find_one({'name': jobName, 'company': company, 'location': location}, no_cursor_timeout = True):
                continue

            self.parse_position_content(item.find('a').get('href'), date, location, salary)

        return True

    def parse_position_content(self, url, date, location, salary):
        if url.find('jobs.51job.com') == -1:
            return

        try:
            r = requests.get(url, headers = headers)
        except:
            return self.parse_position_content(url, date, location, salary)

        page_source = r.text
        soup = BeautifulSoup(page_source, 'html.parser')

        try:
            name = soup.find(class_ = 'tHjob').find('h1').text.strip()
        except:
            name = ''

        try:
            company = soup.find(class_ = 'cname').find('a').text.strip()
        except:
            company = ''

        try:
            description = soup.find(class_ = 'job_msg').text.strip()

            if description.find('职能类别') != -1:
                description = description[:description.find('职能类别')].strip()
        except:
            description = ''

        try:
            exp = re.findall('([^|\s]+)年经验', soup.select('.tHeader.tHjob .msg.ltype')[0].get_text().strip())

            if len(exp) and '-' in exp[0]:
                exp = exp[0].split('-')

            exp = np.array(exp, dtype = int).tolist()
        except:
            exp = []

        try:
            edu = ''

            for i in ['初中', '中专', '大专', '高中', '本科', '研究生', '硕士', '博士']:
                if i in soup.find(class_ = 'msg ltype').text.strip():
                    edu = i
                    break
        except:
            edu = ''

        try:
            count = int(re.sub("\D", "", soup.select('.jtag.inbox .t1 .i3')[0].parent.get_text()))
        except:
            count = ''

        try:
            lang = soup.select('.jtag.inbox .t1 .i5')[0].parent.get_text()
        except:
            lang = ''

        try:
            major = soup.select('.jtag.inbox .t1 .i6')[0].parent.get_text()
        except:
            major = ''

        try:
            welfare = [t.text for t in soup.find(class_ = 'jtag').select('span')]
        except:
            welfare = []

        try:
            funType = soup.find(text = re.compile('职能类别')).parent.find_next_sibling().text
        except:
            funType = ''

        try:
            place = soup.find(text = re.compile('上班地址')).parent.parent.get_text().strip().split('：')[1]
        except:
            place = ''

        try:
            industry = soup.find(class_ = 'com_tag').select('p')[2].get_text()
        except:
            industry = ''

        try:
            logoUrl = 'https:' + soup.find(class_ = 'himg').find('img').get('src')
        except:
            logoUrl = ''

        item = {
            'url': url,
            'edu': edu,
            'exp': exp,
            'name': name,
            'date': date,
            'lang': lang,
            'place': place,
            'major': major,
            'count': count,
            'salary': salary,
            'welfare': welfare,
            'funType': funType,
            'company': company,
            'location': location,
            'logoUrl': logoUrl,
            'industry': industry,
            'platform': 'qiancheng',
            'description': description,
            'stime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }

        if len(item['name']) == 0 or len(item['description']) == 0:
            return

        if not qushu_qiancheng_position.find_one({'name': name, 'company': company, 'location': location}, no_cursor_timeout = True):
            pprint.pprint(item)
            item['token'] = token(item['description'])
            qushu_qiancheng_position.insert_one(item)

        self.cookie.update(r.cookies)

    def parse_salary(self, salary):
        if salary.find('千/月') != -1 or salary.find('千以下/月') != -1 or salary.find('千以上/月') != -1:
            salary = list(np.array(re.match('[\d\.\-]+', salary).group().split('-')).astype(float) * 1000)
        elif salary.find('万/月') != -1 or salary.find('万以上/月') != -1 or salary.find('万以下/月') != -1:
            salary = list(np.array(re.match('[\d\.\-]+', salary).group().split('-')).astype(float) * 10000)
        elif salary.find('万/年') != -1 or salary.find('万以上/年') != -1 or salary.find('万以下/年') != -1:
            salary = list(np.array(re.match('[\d\.\-]+', salary).group().split('-')).astype(float) / 12 * 10000)
        elif salary.find('元/天') != -1 or salary.find('元以上/天') != -1 or salary.find('元以下/天') != -1:
            salary = list(np.array(re.match('[\d\.\-]+', salary).group().split('-')).astype(float) * 30)
        else:
            salary = []

        return salary


def start(keywords):
    QIANCHENG_POST(keywords)


# tech_keywords = [
#     'html5', '架构师', '软件测试', '硬件交互设计师', '深度学习', '数据分析', '运维总监', 'CTO', '硬件测试', 'Android', '机器学习', '网络安全',
#     '机器视觉', 'CMO', '自然语言处理', '数据挖掘', '网络工程师', '数据库', '算法工程师', 'Python', 'Ruby', '游戏特效', '前端', '游戏开发', 'golang',
#     'erlang', '网页设计', '全栈工程师', '搜索算法', 'Hadoop', '运维工程师', 'BI工程师', 'iOS', 'C++', 'c#', 'Java', 'DB2', '.net', 'delphi',
#     '图像识别', 'PHP', '语音识别', 'perl', 'ruby', 'node.js', 'erlang', '爬虫', '数据采集', 'u3d', '测试工程师', '功能测试', '性能测试', '游戏测试',
#     'Flash', '技术合伙人', '系统工程师', '桌面开发', 'WEB安全', '游戏策划', 'Oracle', 'COCOS2D', 'linux', 'unix', 'etl', '数据仓库', 'unity3d',
#     '目标检测', '推荐系统', '安卓开发', '', '云计算', '大数据', '移动端测试', '推荐算法', '驱动开发', '自动驾驶', '图像算法', '音频算法',
#     '运维工程师', '网络工程师', 'IT技术支持', 'DBA', '算法研究员', 'shell', '区块链', '手机测试', '运维开发工程师',
#     '嵌入式', 'windows开发', '人工智能', 'spark', '机器视觉', '智能问答', '人脸识别', 'ai研究员', '知识图谱', '技术总监', '技术主管', '技术副总裁', '数据平台'
# ]

tech_keywords = [
    'Java',
    'PHP',
    'web前端',
    '后端开发',
    'Java',
    'C++',
    'PHP',
    '数据挖掘',
    'C',
    'C#',
    '.NET',
    'Hadoop',
    'Python',
    'Delphi',
    'VB',
    'Perl',
    'Ruby',
    'Node.js',
    '搜索算法',
    'Golang',
    '自然语言处理',
    '推荐算法',
    'Erlang',
    '算法工程师',
    '语音/视频/图形开发',
    '数据采集',
    '移动开发',
    'HTML5',
    'Android',
    'iOS',
    'WP',
    '移动web前端',
    'Flash',
    'JavaScript',
    'U3D',
    'COCOS2DX',
    '测试工程师',
    '自动化测试',
    '功能测试',
    '性能测试',
    '测试开发',
    '移动端测试',
    '游戏测试',
    '硬件测试',
    '软件测试',
    '运维工程师',
    '运维开发工程师',
    '网络工程师',
    '系统工程师',
    'IT技术支持',
    '系统管理员',
    '网络安全',
    '系统安全',
    'DBA',
    '数据',
    'ETL工程师',
    '数据仓库',
    '数据开发',
    '数据挖掘',
    '数据分析师',
    '数据架构师',
    '算法研究员',
    '项目经理',
    '项目主管',
    '项目助理',
    '项目专员',
    '实施顾问',
    '实施工程师',
    '需求分析工程师',
    '硬件',
    '嵌入式',
    '自动化',
    '单片机',
    '电路设计',
    '驱动开发',
    '系统集成',
    'FPGA开发',
    'DSP开发',
    'ARM开发',
    'PCB工艺',
    '模具设计',
    '热传导',
    '材料工程师',
    '精益工程师',
    '射频工程师',
    '前端开发',
    'web前端',
    'Javascript',
    'Flash',
    'HTML5',
    '通信技术工程师',
    '通信研发工程师',
    '数据通信工程师',
    '移动通信工程师',
    '电信网络工程师',
    '电信交换工程师',
    '有线传输工程师',
    '无线射频工程师',
    '通信电源工程师',
    '通信标准化工程师',
    '通信项目专员',
    '通信项目经理',
    '核心网工程师',
    '通信测试工程师',
    '通信设备工程师',
    '光通信工程师',
    '光传输工程师',
    '光网络工程师',
    '电子工程师',
    '电气工程师',
    'FAE',
    '电气设计工程师',
    '高端技术职位',
    '技术经理',
    '技术总监',
    '测试经理',
    '架构师',
    'CTO',
    '运维总监',
    '技术合伙人',
    '人工智能',
    '机器学习',
    '深度学习',
    '图像算法',
    '图像处理',
    '语音识别',
    '图像识别',
    '算法研究员',
    '软件销售支持',
    '售前工程师',
    '售后工程师',
    '其他技术职位',
    '产品经理',
    '产品总监',
    '产品经理',
    '网页产品经理',
    '移动产品经理',
    '产品助理',
    '数据产品经理',
    '电商产品经理',
    '游戏策划',
    '产品专员',
    '高端产品职位',
    '产品总监',
    '游戏制作人',
    '产品VP',
    '其他产品职位',
    'UI设计师',
    '平面设计师',
    '视觉设计',
    '视觉设计师',
    '网页设计师',
    'Flash设计师',
    'APP设计师',
    'UI设计师',
    '平面设计师',
    '美术设计师（2D/3D）',
    '广告设计师',
    '多媒体设计师',
    '原画师',
    '游戏特效',
    '游戏界面设计师',
    '游戏场景',
    '游戏角色',
    '游戏动作',
    '三维/CAD/制图',
    '美工',
    '包装设计',
    '设计师助理',
    '动画设计师',
    '插画师',
    '交互设计师',
    '无线交互设计师',
    '网页交互设计师',
    '硬件交互设计师',
    '数据分析师',
    '用户研究员',
    '游戏数值策划',
    'UX设计师',
    '用户研究经理',
    '用户研究总监',
    '高端设计职位',
    '设计经理/主管',
    '设计总监',
    '视觉设计经理',
    '视觉设计总监',
    '交互设计经理/主管',
    '交互设计总监',
    '非视觉设计',
    '服装设计',
    '工业设计',
    '橱柜设计',
    '家具设计',
    '家居设计',
    '珠宝设计',
    '室内设计',
    '陈列设计',
    '景观设计',
    '其他设计职位',
    '新媒体运营',
    '产品运营',
    '运营',
    '用户运营',
    '产品运营',
    '数据运营',
    '内容运营',
    '活动运营',
    '商家运营',
    '品类运营',
    '游戏运营',
    '网络推广',
    '网站运营',
    '新媒体运营',
    '社区运营',
    '微信运营',
    '微博运营',
    '策略运营',
    '线下拓展运营',
    '电商运营',
    '运营助理/专员',
    '内容审核',
    '销售运营',
    '编辑',
    '副主编',
    '内容编辑',
    '文案策划',
    '网站编辑',
    '记者',
    '采编',
    '售前咨询',
    '售后咨询',
    '网络客服',
    '客服经理',
    '客服专员/助理',
    '客服主管',
    '客服总监',
    '电话客服',
    '咨询热线/呼叫中心客服',
    '高端运营职位',
    '主编',
    '运营总监',
    'COO',
    '客服总监',
    '运营经理/主管',
    '其他运营职位',
    '市场营销',
    '市场推广',
    '选址开发',
    '市场营销',
    '市场策划',
    '市场顾问',
    '市场推广',
    'SEO',
    'SEM',
    '商务渠道',
    '商业数据分析',
    '活动策划',
    '网络营销',
    '海外市场',
    '政府关系',
    'APP推广',
    '公关媒介',
    '媒介经理',
    '广告协调',
    '品牌公关',
    '媒介专员',
    '活动策划执行',
    '媒介策划',
    '广告',
    '广告创意',
    '美术指导',
    '广告设计师',
    '策划经理',
    '文案',
    '广告制作',
    '媒介投放',
    '媒介合作',
    '媒介顾问',
    '广告审核',
    '高端市场职位',
    '市场总监',
    'CMO',
    '公关总监',
    '媒介总监',
    '创意总监',
    '其他市场职位',
    '人事/HR',
    '行政',
    '财务',
    '人力资源主管',
    '招聘',
    'HRBP',
    '人力资源专员',
    '培训',
    '薪资福利',
    '绩效考核',
    '人力资源经理',
    '人力资源VP',
    '人力资源总监',
    '员工关系',
    '组织发展',
    '行政专员',
    '前台',
    '行政主管',
    '经理助理',
    '后勤',
    '商务司机',
    '行政经理',
    '行政总监',
    '财务',
    '会计',
    '出纳',
    '财务顾问',
    '结算',
    '税务',
    '审计',
    '风控',
    '财务经理',
    'CFO',
    '财务总监',
    '财务主管',
    '法务专员/助理',
    '律师',
    '专利',
    '法律顾问',
    '法务主管',
    '法务经理',
    '法务总监',
    '其他职能职位',
    'CEO/总裁/总经理',
    '高级管理职位',
    'CEO/总裁/总经理',
    '副总裁/副总经理',
    '合伙人',
    '创始人',
    '董事会秘书',
    '销售专员',
    '销售经理',
    '销售',
    '销售专员',
    '销售经理',
    '客户代表',
    '大客户代表',
    'BD经理',
    '商务渠道',
    '渠道销售',
    '代理商销售',
    '销售助理',
    '电话销售',
    '销售顾问',
    '商品经理',
    '广告销售',
    '网络营销',
    '营销主管',
    '销售工程师',
    '客户经理',
    '销售管理',
    '销售总监',
    '商务总监',
    '区域总监',
    '城市经理',
    '销售VP',
    '团队经理',
    '文案',
    '广告创意',
    '编辑',
    '记者',
    '编辑',
    '采编',
    '撰稿人',
    '出版发行',
    '校对录入',
    '总编',
    '自媒体',
    '公关媒介',
    '媒介经理',
    '媒介专员',
    '广告协调',
    '品牌公关',
    '活动策划执行',
    '媒介策划',
    '会务会展',
    '广告',
    '广告创意',
    '美术指导',
    '广告设计师',
    '策划经理',
    '文案',
    '广告制作',
    '媒介投放',
    '媒介合作',
    '媒介顾问',
    '广告审核',
    '影视媒体',
    '助理',
    '统筹制片人',
    '执行制片人',
    '导演/编导',
    '摄影/影像师',
    '视频编辑',
    '音频编辑',
    '经纪人',
    '后期制作',
    '影视制作',
    '影视发行',
    '影视策划',
    '放映管理',
    '录音/音效',
    '制片人',
    '编剧',
    '其他传媒职位',
    '投资经理',
    '投资总监',
    '风控',
    '投融资',
    '投资经理',
    '行业研究',
    '资产管理',
    '投资总监',
    '投资VP',
    '投资合伙人',
    '融资',
    '并购',
    '投后管理',
    '投资助理',
    '投资顾问',
    '风控',
    '律师',
    '资信评估',
    '合规稽查',
    '审计',
    '法务',
    '会计',
    '清算',
    '银行',
    '信用卡销售',
    '分析师',
    '柜员',
    '商务渠道',
    '大堂经理',
    '理财顾问',
    '客户经理',
    '信贷管理',
    '风控',
    '互联网金融',
    '金融产品经理',
    '风控',
    '催收员',
    '分析师',
    '投资经理',
    '交易员',
    '理财顾问',
    '合规稽查',
    '审计',
    '清算',
    '保险业务',
    '精算师',
    '保险理赔',
    '证券',
    '证券经纪人',
    '证券分析师',
    '其他金融职位',
    '汽车销售',
    '汽车维修',
    '汽车设计',
    '车身设计',
    '底盘设计',
    '机械设计',
    '动力系统设计',
    '电子工程设计',
    '零部件设计',
    '汽车工程项目管理',
    '内外饰设计工程师',
    '总装工程师',
    '焊接工程师',
    '冲压工程师',
    '质量工程师',
    '汽车销售与制造',
    '汽车销售',
    '汽车配件销售',
    '汽车售后服务',
    '汽车维修',
    '汽车美容',
    '汽车定损理赔',
    '二手车评估师',
    '4S店管理',
    '汽车改装工程师',
    '其他汽车职位',
    '课程设计',
    '教务管理',
    '教育产品研发',
    '课程设计',
    '课程编辑',
    '教师',
    '培训研究',
    '培训师',
    '培训策划',
    '其他教育产品研发职位',
    '教育行政',
    '校长',
    '教务管理',
    '教学管理',
    '班主任/辅导员',
    '教师',
    '助教',
    '高中教师',
    '初中教师',
    '小学教师',
    '幼教',
    '理科教师',
    '文科教师',
    '外语教师',
    '音乐教师',
    '美术教师',
    '体育教师',
    '就业老师',
    'IT培训',
    'JAVA培训讲师',
    'Android培训讲师',
    'ios培训讲师',
    'PHP培训讲师',
    '.NET培训讲师',
    'C++培训讲师',
    'Unity 3D培训讲师',
    'Web前端培训讲师',
    '软件测试培训讲师',
    '动漫培训讲师',
    'UI设计培训讲师',
    '财会培训讲师',
    'HR培训讲师',
    '培训师',
    '拓展培训',
    '课程顾问',
    '招生顾问',
    '留学顾问',
    '教练',
    '舞蹈教练',
    '瑜伽教练',
    '瘦身顾问',
    '游泳教练',
    '健身教练',
    '篮球/羽毛球教练',
    '跆拳道教练',
    '其他教育培训职位',
    '药剂师',
    '营养师',
    '医生/医技',
    '医生助理',
    '医学影像',
    'B超医生',
    '中医',
    '医师',
    '心理医生',
    '药剂师',
    '牙科医生',
    '康复治疗师',
    '验光师',
    '放射科医师',
    '检验科医师',
    '医师',
    '其他医生职位',
    '护士长',
    '护士/护理',
    '导医',
    '健康整形',
    '营养师',
    '整形师',
    '理疗师',
    '针灸推拿',
    '生物制药',
    '药品注册',
    '药品生产',
    '临床研究',
    '临床协调',
    '临床数据分析',
    '医学总监',
    '医药研发',
    '医疗器械注册',
    '医疗器械生产/质量管理',
    '医疗器械研究',
    '药店',
    '店长',
    '执业药师/驻店药师',
    '店员/营业员',
    '市场营销/媒体',
    '医疗器械销售',
    '医学编辑',
    '医学总监',
    '药学编辑',
    '医药代表',
    '健康顾问',
    '医美咨询',
    '其他医疗健康类职位',
    '采购经理',
    '采购主管',
    '采购',
    '采购总监',
    '采购经理',
    '采购专员',
    '买手',
    '采购工程师',
    '采购主管',
    '采购助理',
    '进出口贸易',
    '外贸经理',
    '外贸专员',
    '外贸业务员',
    '贸易跟单',
    '其他采购/贸易类职位',
    '物流专员',
    '贸易跟单',
    '物流',
    '供应链专员',
    '供应链经理',
    '物流专员',
    '物流经理',
    '物流运营',
    '物流跟单',
    '贸易跟单',
    '物仓调度',
    '物仓项目',
    '运输经理/主管',
    '货运代理专员',
    '货运代理经理',
    '水/空/陆运操作',
    '报关员',
    '报检员',
    '核销员',
    '单证员',
    '仓储',
    '仓储物料经理',
    '仓储物料专员',
    '仓储物料项目',
    '仓储管理',
    '仓库文员',
    '配/理/拣/发货',
    '运输',
    '货运司机',
    '集装箱管理',
    '配送',
    '快递',
    '高端供应链职位',
    '供应链总监',
    '物流总监',
    '其他供应链职位',
    '物业管理',
    '房地产规划开发',
    '房产策划',
    '地产项目管理',
    '地产招投标',
    '设计装修与市政建设',
    '高级建筑工程师',
    '建筑工程师',
    '建筑设计师',
    '土木/土建/结构工程师',
    '室内设计',
    '园林设计',
    '城市规划设计',
    '工程监理',
    '工程造价',
    '预结算',
    '工程资料管理',
    '建筑施工现场管理',
    '房地产经纪',
    '地产置业顾问',
    '地产评估',
    '地产中介',
    '物业管理',
    '物业租赁销售 ',
    '物业招商管理',
    '高端房地产职位',
    '地产项目总监',
    '地产策划总监',
    '地产招投标总监',
    '物业总监',
    '房地产销售总监',
    '其他房地产职位',
    '企业管理咨询',
    '咨询/调研',
    '企业管理咨询',
    '数据分析师',
    '财务咨询顾问',
    'IT咨询顾问',
    '人力资源顾问',
    '咨询项目管理',
    '战略咨询',
    '猎头顾问',
    '市场调研',
    '其他咨询顾问',
    '知识产权',
    '事务所律师',
    '公司法务',
    '英语翻译',
    '日语翻译',
    '韩语/朝鲜语翻译',
    '法语翻译',
    '德语翻译',
    '俄语翻译',
    '西班牙语翻译',
    '其他语种翻译',
    '高端咨询类职位',
    '咨询总监',
    '咨询经理',
    '高级翻译',
    '同声传译  ',
    '其他咨询/翻译类职位',
    '实习生',
    '管培生',
    '实习生',
    '管理培训生',
    '储备干部',
    '其他实习/培训/储备职位',
    '旅游顾问',
    '导游',
    '旅游服务',
    '计调',
    '签证',
    '旅游顾问',
    '导游',
    '预定票务',
    '旅游产品开发/策划',
    '旅游产品经理',
    '旅游策划师',
    '其他旅游职位',
    '酒店前台',
    '客房服务员',
    '保安',
    '保洁',
    '酒店',
    '收银',
    '酒店前台',
    '客房服务员',
    '酒店经理',
    '后厨',
    '配菜打荷',
    '茶艺师',
    '西点师',
    '餐饮',
    '收银',
    '服务员',
    '厨师',
    '咖啡师',
    '送餐员',
    '餐饮店长',
    '领班',
    '督导/巡店',
    '陈列员',
    '理货员',
    '零售',
    '收银',
    '导购',
    '店员/营业员',
    '门店店长',
    '发型师',
    '美甲师',
    '化妆师',
    '健身',
    '瑜伽教练',
    '瘦身顾问',
    '游泳教练',
    '美体教练',
    '美容师/顾问',
    '舞蹈教练',
    '健身教练',
    '其他服务业职位',
    '生产总监',
    '安全员',
    '生产营运',
    '厂长/工厂经理',
    '生产总监',
    '生产经理/车间主任',
    '生产组长/拉长',
    '生产员',
    '生产设备管理',
    '生产计划/物料控制',
    '生产跟单',
    '质量管理/测试',
    '可靠度工程师',
    '故障分析师',
    '认证工程师',
    '体系工程师',
    '审核员',
    '安全员',
    '机械设计/制造',
    '机械工程师',
    '机械设计师',
    '机械设备工程师',
    '机械维修/保养',
    '机械制图',
    '机械结构工程师',
    '工业工程师',
    '工艺/制程工程师',
    '材料工程师',
    '机电工程师',
    'CNC/数控',
    '冲压工程师',
    '夹具工程师',
    '模具工程师',
    '焊接工程师',
    '注塑工程师',
    '铸造/锻造工程师',
    '化工',
    '化工工程师',
    '实验室技术员',
    '化学分析',
    '涂料研发',
    '化妆品研发',
    '服装设计',
    '女装设计',
    '男装设计',
    '童装设计',
    '内衣设计',
    '面料设计'
]

if __name__ == '__main__':
    from optparse import OptionParser

    parser = OptionParser(usage = "%prog [options]")
    parser.add_option("-p", "--process", action = "store", type = "int", dest = "count", help = "the count of process", default = 10)
    parser.add_option("-e", "--network", action = "store", type = "str", dest = "address", help = "the address of mongodb", default = 'localhost')

    options, args = parser.parse_args()

    client = MongoClient(options.address, 27017, connect = False)

    qushu_qiancheng_db = client['qushu_qiancheng_db']
    qushu_qiancheng_position = qushu_qiancheng_db['qushu_qiancheng_position']

    with open('keywords.txt', 'r') as file:
        keywords = list(set([word.strip() for word in file.readlines()] + tech_keywords))
        random.shuffle(keywords)

    proc_list = []

    seg = int(len(keywords) / options.count)

    for i in range(options.count):
        p = Process(target = start, args = (keywords[seg * i:seg * (i + 1)],))
        proc_list.append(p)

    for p in proc_list:
        p.start()

    for p in proc_list:
        p.join()
